package br.com.gaspar.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.text.MessageFormat;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Classe utilitária para executar web services de forma simplificada
 * @author gaspar
 *
 */
public class WebServiceUtil implements Serializable {
	
	private static final long serialVersionUID = 8106329461677959030L;

    private static Logger log = LoggerFactory.getLogger(WebServiceUtil.class);

    public static String ENVELOPE_SOAP_CNE = 
            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
                              "xmlns:con=\"http://consultaWS.nfe.sefaz.gov/\">" +
                  "<soapenv:Header/>" +
                  "<soapenv:Body>" +
                      "<con:consultar>" +
                          "<tpAmb>{0}</tpAmb>" +
                          "<cnpj>{1}</cnpj>" +
                      "</con:consultar>" +
                  "</soapenv:Body>" +
              "</soapenv:Envelope>";
    
    public static String ENVELOPE_SOAP_TRANSITO = 
            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
                              "xmlns:con=\"http://consultaWS.nfe.sefaz.gov/\">" +
                  "<soapenv:Header/>" +
                  "<soapenv:Body>" +
                      "<con:consultar>" +
                          "<tpAmb>{0}</tpAmb>" +
                          "<chaveAcesso>{1}</chaveAcesso>" +
                      "</con:consultar>" +
                  "</soapenv:Body>" +
              "</soapenv:Envelope>";

	private static String envelope =
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                    "<soap:Header>" +
                        "<nfeCabecMsg xmlns=\"{0}\">" +
                            "<cUF>50</cUF>" +
                            "<indComp>0</indComp>" +
                            "<versaoDados>2.00</versaoDados>" +
                        "</nfeCabecMsg>" +
                    "</soap:Header>" +
                    "<soap:Body>" +
                        "<{1} xmlns=\"{0}\">" +
                            "<nfeDadosMsg>{2}</nfeDadosMsg>" +
                        "</{1}>" +
                    "</soap:Body>" +
                "</soap:Envelope>";

    public static String criarEnvelope(String namespace, String operation, String conteudo) {
        return MessageFormat.format(envelope, namespace, operation, conteudo);
    }
    
    /**
     * Preenche o envelope com os dados passados no parâmetros respeitando a ordem de cada elemento
     * @param envelope
     * @param dados
     * @return
     * 
     * @author gaspar
     */
    public static String preencherEnvelope(String envelopeSOAP, Object... dados) {
        return MessageFormat.format(envelopeSOAP, dados);
    }
	
	/**
	 * Executa web service fixando o protocolo SOAP para versão 1.1
	 * @param envelope
	 * @param urlAddress
	 * @return
	 */
	public static String executarWebService(String envelope, String urlAddress) {
        String result = executarWebService(envelope, urlAddress, SOAPConstants.SOAP_1_1_PROTOCOL, 10);
        return result;
    }
	
	/**
	 * Executa web service com base na versão do protocolo SOAP informado e timeout em segundos, ex: SOAPConstants.SOAP_1_2_PROTOCOL
	 * @param envelope
	 * @param urlAddress
	 * @param soapProtocol
	 * @param timeout  - tempo em segundos
	 * @return
	 */
	public static String executarWebService(String envelope, String urlAddress, String soapProtocol, final Integer timeout) {
        String result = "";

        try {
            MessageFactory factory = MessageFactory.newInstance(soapProtocol);
            SOAPMessage message;
            try {                
                message = factory.createMessage(null, new ByteArrayInputStream(envelope.getBytes()));
                SOAPConnection con = SOAPConnectionFactory.newInstance().createConnection();
                java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                URL url = new URL(null, urlAddress,
                        new URLStreamHandler() { // Anonymous (inline) class

                            @Override
                            protected URLConnection openConnection(URL url) throws IOException {
                                URL clone_url = new URL(url.toString());
                                URLConnection clone_urlconnection = clone_url.openConnection();

                                // TimeOut settings
                                clone_urlconnection.setReadTimeout(timeout * 1000);
                                clone_urlconnection.setConnectTimeout(timeout * 1000);                                
                                return ((HttpURLConnection) clone_urlconnection);
                            }
                        });

                SOAPMessage res = con.call(message, url);

                ByteArrayOutputStream out = new ByteArrayOutputStream();

                res.writeTo(out);

                result = out.toString();
                
                out.close();
                con.close();
                } catch (IOException ex) {
            		log.info("Erro", ex);
            	}
        } catch (SOAPException ex) {
            ex.printStackTrace();
            log.info("Erro", ex);
        }
        return result;
    }
    
    public static String normalizarXML(String texto) {
        return texto.replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;").replace("\n", "").replace("\r", "&#xD;");
    }

    public static String desnormalizarXML(String texto) {
        return texto.replace("&lt;", "<").replace("&gt;", ">").replace("&quot;", "\"").replace("&#xD;", "\r");
    }

}
